/*++

Copyright (c) 2007  Microsoft Corporation 

Filename: 

    Application.cs

Abstract: 

    This file is an Interface for Visio application
     
--*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Globalization;
using Visio = Microsoft.Office.Interop.Visio;
using System.Windows.Forms;

namespace NRTMAddIn
{
    /// <summary>
    /// Interface for Visio application
    /// </summary>
    class Application
    {
        #region Private variables
        
        //Table to store all open document reference
        private static Hashtable nrtm_documents;
             
        #endregion        

        #region Constructors

        /// <summary>
        /// Default Constructor.
        /// </summary>
        public Application()
        {
            //Left blank
        }

        /// <summary>
        /// Constructor - overridden.
        /// </summary>
        /// <param name="visioApplication">
        ///  Visio application reference
        /// </param>
        public Application(Visio.Application visioApplication)
        {
            if (visioApplication == null)
            {
                return;
            }

            try
            {
                //Table to store all documents
                nrtm_documents = new Hashtable();

                //Initializa NRTM menu, events and data tables
                Global.VisioApp = visioApplication;
                
                SetupVisioEvents();
            }
            catch (NrtmException ex)
            {
                //To catch exceptions from current functions
                throw new NrtmException("Application Constructor", ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                throw new NrtmException("Application Constructor", ex);
            }
        }

        #endregion

        #region Events
        /// <summary>
        /// Before Document Close Event
        /// </summary>
        /// <param name="visioDocument"></param>
        void VisioApp_BeforeDocumentClose(Visio.Document visioDocument)
        {
            try
            {
                // get the document name
                string fullName = visioDocument.FullName.ToLower(CultureInfo.CurrentCulture);

                if (fullName.EndsWith(".vss") ||
                    fullName.EndsWith(".vsx") ||
                    visioDocument.Type == Visio.VisDocumentTypes.visTypeStencil)
                {
                    // do not create a document wrapper for this document
                    return;
                }

                if (!Convert.ToBoolean((short)visioDocument.DocumentSheet.get_CellExistsU(
                                      Global.DocTemplateUserProp, 0)))
                {
                    // Consider documents created using addin template only
                    return;
                }

                // Look through the document wrapper classes and find the one the corresponds with
                // the Visio document that is closing.
                Document docToRemove = GetDocumentObject(visioDocument);

                // If we found a document wrapper, then remove it from our collection.
                if (docToRemove != null)
                {
                    nrtm_documents.Remove(docToRemove.UniqueID);
                }
            }
            catch (Exception ex)
            {
                NrtmException.HandleExceptions(ex);
            }
        }

        /// <summary>
        /// Event to handle Document Created or Opened
        /// </summary>
        /// <param name="visioDocument"></param>
        void VisioApp_DocumentCreatedOpened(Visio.Document visioDocument)
        {
            try
            {
                // get the document name
                string fullName = visioDocument.FullName.ToLower(CultureInfo.CurrentCulture);

                if (fullName.EndsWith(".vss") ||
                    fullName.EndsWith(".vsx") ||
                    visioDocument.Type == Visio.VisDocumentTypes.visTypeStencil)
                {
                    // do not create a document wrapper for this document
                    return;
                }

                if (!Convert.ToBoolean((short)visioDocument.DocumentSheet.get_CellExistsU(
                                      Global.DocTemplateUserProp, 0)))
                {
                    // Consider documents created using addin template only
                    return;
                }

                bool docSavedState = visioDocument.Saved;

                //Create new Document object for new Visio document
                Document newDocument = new Document(visioDocument);

                // add this new document to our collection
                if (newDocument != null)
                {
                    // add the item to the collection
                    nrtm_documents.Add(newDocument.UniqueID, newDocument);
                }

                // reset the saved state of the document after we have done our work
                visioDocument.Saved = docSavedState;
            }
            catch (NrtmException ex)
            {
                //To catch and display exceptions from sub functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                NrtmException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
        }

        #endregion Events

        #region Methods

        /// <summary>
        /// Setup the event sinks to the Visio.Application class.
        /// </summary>
        private void SetupVisioEvents()
        {
            try
            {
                // setup the delegates for the Visio.Application object
                Global.VisioApp.DocumentCreated += new 
                    Microsoft.Office.Interop.Visio.EApplication_DocumentCreatedEventHandler
                    (VisioApp_DocumentCreatedOpened);
                Global.VisioApp.DocumentOpened += new 
                    Microsoft.Office.Interop.Visio.EApplication_DocumentOpenedEventHandler
                    (VisioApp_DocumentCreatedOpened);
                Global.VisioApp.BeforeDocumentClose += new 
                    Microsoft.Office.Interop.Visio.EApplication_BeforeDocumentCloseEventHandler
                    (VisioApp_BeforeDocumentClose);

            }
            catch (Exception ex)
            {
                //To catch exceptions from current functions
                throw new NrtmException("Setup events", ex);
            }
            return;
        }

        /// <summary>
        /// Delete visio events before exit
        /// </summary>
        public void DeleteVisioEvents()
        {
            //Clear events
            Global.VisioApp.DocumentCreated -= VisioApp_DocumentCreatedOpened;
            Global.VisioApp.DocumentOpened -= VisioApp_DocumentCreatedOpened;
            Global.VisioApp.BeforeDocumentClose -= VisioApp_BeforeDocumentClose;

            // delete document level events and menu
            foreach (Document doc in nrtm_documents.Values)
            {
                doc.DeleteVisioEvents();
            }
        }

        /// <summary>
        /// Fetch the reference to Document object from the hashtable
        /// </summary>
        /// <param name="visioDocument"></param>
        /// <returns></returns>
        internal static Document GetDocumentObject(Visio.Document visioDocument)
        {
            try
            {
                foreach (Document doc in nrtm_documents.Values)
                {
                    if (String.Compare(visioDocument.Name, doc.VisioDocument.Name) == 0)
                    {
                        return doc;
                    }
                }
            }
            catch (System.NullReferenceException ex)
            {
                //Handle the error for hash table access
                NrtmException.HandleExceptions(ex);
            }
            catch (Exception ex)
            {
                //Handle the error for hash table access
                NrtmException.HandleExceptions(ex);
            }
            return null;
        }

        #endregion Methods
    }
}
